-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Add a promise_test sequencing clarification #17924
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
I got bitten by a nasty race condition where a failed `promise_rejects` caused teardown logic to run after the next test had already started, interfering with the next test's state. Since this was unexpected, here's a proposed addition to the documentation to make this clearer. Let me know if I'm misunderstanding how this works, or if you think this should be changed in promise_test instead. (For context, see #17898 which contains a fix to a test helper affected by this.)
If I'm remembering right, the sequence turned out to be something like this:
As a result, if the tested promise is part of a chain, the following steps in the chain were happening after the |
How could the case fixed by gh-17898 be handled in |
In the current (unpatched) version of the code, cleanup logic is located in a fulfillment handler for a Promise supplied to testharness.js. When the Promise rejects (e.g. for those tests that expect failure), then I wouldn't expect the fulfillment handler (and therefore the cleanup logic) to run at all. That said, it sounds like you were seeing the cleanup code executing. Is that right? |
The malfunctioning test in my patch was the newly added If I'm understanding it right, the problem was that the unexpectedly not-rejected promise is indeed leading to a test failure in |
To clarify, I'm not sure what the expected behavior is if a test file contains multiple failing test. The overall state was still "Failure" as it should be, but it was very confusing to me that I couldn't consistently get test failures reported for both of the tests where I expected failures since the underlying functionality wasn't implemented yet Depending on the order of the tests, I was either getting the second test to pass unexpectedly, or having it fail with an unrelated error due to losing its device in the middle of the test. After making the change to use |
Whether there's one failing test or multiple, the expected behavior is the same. The part that I'm trying to understand is how and why code in one test was still running after the test had failed. Sometimes, that happens because a Promise is accidentally discarded. The current (pre- I can't explain that, though. If the harness was correctly reporting a test failure, then that means the Promise was rejected, and since Am I interpreting your experience correctly? |
Not quite, it's confusing since this is an expected failure due to a promise that was supposed to be rejected but actually succeeded. Specifically, the "Non-immersive session rejects local space if not requested" test calls The part I'm not entirely clear on is why the harness doesn't wait for the overall promise chain to resolve, but instead proceeds to |
FYI, I initially had the wrong promise-returning call in the previous comment, it's supposed to be See also my earlier comment #17924 (comment) where I tried to trace the execution sequence - please take that with a grain of salt since I'm not familiar with the code and tend to get confused by async programming. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor copy-editing nits
After a bit of experimentation, it doesn't look like there's much we can do about this in the framework itself. I generally recommend reserving APIs like My initial thought was to enforce the recommendation in code by rejecting tests which mix paradigms. This doesn't appear to be feasible because many utilities (e.g. A more lax solution might be to wait for the So I think we'll have to settle (Promise humor) for documentation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
However, be aware that a test is considered finished as soon as its status is resolved, and a failed test's chained actions may still be in progress when the next test starts.
The term "status" has a specific meaning in testharness.js, so using it to describe a different concept may confuse readers. The term "actions" isn't defined for the web platform or for testharness.js. Rather than improve the wording, I suggest removing the sentence. The second sentence is what's important for test authors.
The code font quote overrode the intended linking
jugglinmike@ wrote:
Ah, so was part of the issue that my
Removed, though I think the result looks a bit odd - I'd intuitively interpret "finished" from the first sentence as being equivalent to "settled", and if that's not the case I think it would be helpful to say so explicitly. Yes, following the instructions would avoid issues, but people may still end up with an incorrect mental model. I'm OK proceeding as-is with the suggested changes incorporated, but how would you feel about something like this? ... don't start running until after the previous Promise Test finishes.
+ However, a failing test can finish while chained promises are not yet settled.
Use [add_cleanup](#cleanup) to register ... ... don't start running until after the previous Promise Test finishes.
+ However, a failing test does not wait for the overall `promise_test` to settle, so
+ code in a `catch`/`finally` branch may run concurrently with the next test.
Use [add_cleanup](#cleanup) to register ... |
This behavior isn't limited to failing tests. Authors risk interleaved execution any time the promise_test((t) => {
t.done();
return Promise.resolve();
}); We could explain this more thoroughly, but I still think the intricacies will be more distracting than helpful for the first-time contributor. As a middle ground, we could hand-wave the details and reference this discussion. ... don't start running until after the previous Promise Test finishes.
+ [Under rare
+ circumstances](https://github.com/web-platform-tests/wpt/pull/17924), the
+ next test may begin to execute before the returned promise has settled.
Use [add_cleanup](#cleanup) to register ... That makes the finer points available to those who care and avoids confusing those who are looking for direct instruction. What do you think? |
That sounds fine with me, I incorporated that suggestion. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great!
* Add a promise_test sequencing clarification I got bitten by a nasty race condition where a failed `promise_rejects` caused teardown logic to run after the next test had already started, interfering with the next test's state. Since this was unexpected, here's a proposed addition to the documentation to make this clearer. Let me know if I'm misunderstanding how this works, or if you think this should be changed in promise_test instead. (For context, see web-platform-tests#17898 which contains a fix to a test helper affected by this.) * Delete sentence as suggested, s/needed/necessary/ * Re-wrap paragraph * Fix "add_cleanup" link The code font quote overrode the intended linking * Add jugglinmike@'s proposed clarification * Remove trailing whitespace
This addresses some of the flakiness in the sensors tests, in addition to helping make it easier to find other sources of flakiness. Instead of calling GenericSensorTest.reset() in a `finally` clause, use t.add_cleanup() instead. The latter's behavior is more deterministic (see #17924), and fixes an issue where an EventWatcher would fail an assertion when receiving an unexpected event, and GenericSensorTest.reset() would either not be called or called after other tests had already started running. Bug: 731018 Change-Id: Ifbb95b8067b153b70ecb3e6509f476164afd022e
This addresses some of the flakiness in the sensors tests, in addition to helping make it easier to find other sources of flakiness. Instead of calling GenericSensorTest.reset() in a `finally` clause, use t.add_cleanup() instead. The latter's behavior is more deterministic (see #17924), and fixes an issue where an EventWatcher would fail an assertion when receiving an unexpected event, and GenericSensorTest.reset() would either not be called or called after other tests had already started running. Bug: 731018 Change-Id: Ifbb95b8067b153b70ecb3e6509f476164afd022e Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2203378 Auto-Submit: Raphael Kubo da Costa <raphael.kubo.da.costa@intel.com> Commit-Queue: Reilly Grant <reillyg@chromium.org> Reviewed-by: Reilly Grant <reillyg@chromium.org> Cr-Commit-Position: refs/heads/master@{#769442}
This addresses some of the flakiness in the sensors tests, in addition to helping make it easier to find other sources of flakiness. Instead of calling GenericSensorTest.reset() in a `finally` clause, use t.add_cleanup() instead. The latter's behavior is more deterministic (see #17924), and fixes an issue where an EventWatcher would fail an assertion when receiving an unexpected event, and GenericSensorTest.reset() would either not be called or called after other tests had already started running. Bug: 731018 Change-Id: Ifbb95b8067b153b70ecb3e6509f476164afd022e Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2203378 Auto-Submit: Raphael Kubo da Costa <raphael.kubo.da.costa@intel.com> Commit-Queue: Reilly Grant <reillyg@chromium.org> Reviewed-by: Reilly Grant <reillyg@chromium.org> Cr-Commit-Position: refs/heads/master@{#769442}
This addresses some of the flakiness in the sensors tests, in addition to helping make it easier to find other sources of flakiness. Instead of calling GenericSensorTest.reset() in a `finally` clause, use t.add_cleanup() instead. The latter's behavior is more deterministic (see web-platform-tests/wpt#17924), and fixes an issue where an EventWatcher would fail an assertion when receiving an unexpected event, and GenericSensorTest.reset() would either not be called or called after other tests had already started running. Bug: 731018 Change-Id: Ifbb95b8067b153b70ecb3e6509f476164afd022e Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2203378 Auto-Submit: Raphael Kubo da Costa <raphael.kubo.da.costa@intel.com> Commit-Queue: Reilly Grant <reillyg@chromium.org> Reviewed-by: Reilly Grant <reillyg@chromium.org> Cr-Commit-Position: refs/heads/master@{#769442}
…in a cleanup function., a=testonly Automatic update from web-platform-tests sensors: Call GenericSensorTest.reset() in a cleanup function. This addresses some of the flakiness in the sensors tests, in addition to helping make it easier to find other sources of flakiness. Instead of calling GenericSensorTest.reset() in a `finally` clause, use t.add_cleanup() instead. The latter's behavior is more deterministic (see web-platform-tests/wpt#17924), and fixes an issue where an EventWatcher would fail an assertion when receiving an unexpected event, and GenericSensorTest.reset() would either not be called or called after other tests had already started running. Bug: 731018 Change-Id: Ifbb95b8067b153b70ecb3e6509f476164afd022e Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2203378 Auto-Submit: Raphael Kubo da Costa <raphael.kubo.da.costa@intel.com> Commit-Queue: Reilly Grant <reillyg@chromium.org> Reviewed-by: Reilly Grant <reillyg@chromium.org> Cr-Commit-Position: refs/heads/master@{#769442} -- wpt-commits: e909362eb429426f97d3c8731855075de9def0b2 wpt-pr: 23629
…in a cleanup function., a=testonly Automatic update from web-platform-tests sensors: Call GenericSensorTest.reset() in a cleanup function. This addresses some of the flakiness in the sensors tests, in addition to helping make it easier to find other sources of flakiness. Instead of calling GenericSensorTest.reset() in a `finally` clause, use t.add_cleanup() instead. The latter's behavior is more deterministic (see web-platform-tests/wpt#17924), and fixes an issue where an EventWatcher would fail an assertion when receiving an unexpected event, and GenericSensorTest.reset() would either not be called or called after other tests had already started running. Bug: 731018 Change-Id: Ifbb95b8067b153b70ecb3e6509f476164afd022e Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2203378 Auto-Submit: Raphael Kubo da Costa <raphael.kubo.da.costa@intel.com> Commit-Queue: Reilly Grant <reillyg@chromium.org> Reviewed-by: Reilly Grant <reillyg@chromium.org> Cr-Commit-Position: refs/heads/master@{#769442} -- wpt-commits: e909362eb429426f97d3c8731855075de9def0b2 wpt-pr: 23629
…in a cleanup function., a=testonly Automatic update from web-platform-tests sensors: Call GenericSensorTest.reset() in a cleanup function. This addresses some of the flakiness in the sensors tests, in addition to helping make it easier to find other sources of flakiness. Instead of calling GenericSensorTest.reset() in a `finally` clause, use t.add_cleanup() instead. The latter's behavior is more deterministic (see web-platform-tests/wpt#17924), and fixes an issue where an EventWatcher would fail an assertion when receiving an unexpected event, and GenericSensorTest.reset() would either not be called or called after other tests had already started running. Bug: 731018 Change-Id: Ifbb95b8067b153b70ecb3e6509f476164afd022e Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2203378 Auto-Submit: Raphael Kubo da Costa <raphael.kubo.da.costa@intel.com> Commit-Queue: Reilly Grant <reillyg@chromium.org> Reviewed-by: Reilly Grant <reillyg@chromium.org> Cr-Commit-Position: refs/heads/master@{#769442} -- wpt-commits: e909362eb429426f97d3c8731855075de9def0b2 wpt-pr: 23629
I got bitten by a nasty race condition where a failed
promise_rejects
caused teardown logic to run after the next test had already started, interfering with the next test's state. Since this was unexpected, here's a proposed addition to the documentation to make this clearer. Let me know if I'm misunderstanding how this works, or if you think this should be changed in promise_test instead.(For context, see #17898 which contains a fix to a test helper affected by this.)